package com.kuaimacode.kframework.api.service.user;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.kuaimacode.kframework.api.controller.pay.AlipayController;
import com.kuaimacode.kframework.api.controller.pay.WxpayController;
import com.kuaimacode.kframework.api.controller.pay.XcxpayController;
import com.kuaimacode.kframework.api.service.*;
import com.kuaimacode.kframework.api.service.category.AgentServService;
import com.kuaimacode.kframework.api.vo.request.NearOrderReq;
import com.kuaimacode.kframework.api.vo.response.HistoryOrderResp;
import com.kuaimacode.kframework.api.vo.response.MasterTitleMessageResp;
import com.kuaimacode.kframework.api.vo.response.OrderNearResp;
import com.kuaimacode.kframework.api.vo.response.UserPartnerResp;
import com.kuaimacode.kframework.common.Constant;
import com.kuaimacode.kframework.constants.MasterConstants;
import com.kuaimacode.kframework.exception.ErrorEnum;
import com.kuaimacode.kframework.exception.ServerInternalErrorException;
import com.kuaimacode.kframework.mybatis.mapper.user.OrderMapper;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgent;
import com.kuaimacode.kframework.mybatis.models.agent.SysAgentCategoryCfg;
import com.kuaimacode.kframework.mybatis.models.category.AgentServ;
import com.kuaimacode.kframework.mybatis.models.coupon.UserCoupon;
import com.kuaimacode.kframework.mybatis.models.master.MasterOrderAccitity;
import com.kuaimacode.kframework.mybatis.models.master.MasterWaitResp;
import com.kuaimacode.kframework.mybatis.models.sys.Dict;
import com.kuaimacode.kframework.mybatis.models.sysparam.SysParam;
import com.kuaimacode.kframework.mybatis.models.user.*;
import com.kuaimacode.kframework.util.DateUtil;
import com.kuaimacode.kframework.util.DictUtil;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author 中元
 * @date 2019/03/18
 */
@Service
public class OrderService extends ServiceImpl<OrderMapper, Order> {
    @Autowired
    private UserService userService;
    @Autowired
    private UserCouponService userCouponService;

    @Autowired
    private UserAccountDetailService detailService;

    @Autowired
    private AgentServService agentServService;
    @Autowired
    private SysParamService sysParamService;

    @Autowired
    private AddressService addressService;

    @Autowired
    private AgentService agentServices;

    @Autowired
    private SysAgentCategoryCfgService cfgService;

    @Autowired
    private MasterOrderAccitityService accitityService;

    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private UserAccountDetailService userAccountDetailService;

    @Autowired
    private UserMasterService userMasterService;

    @Autowired
    private OrderDispatchService orderDispatchService;
    @Autowired
    private MasterService masterServices;
    @Autowired
    private AgentAccountDetailService agentAccountDetailService;

    @Autowired
    private AlipayController alipayController;
    @Autowired
    private WxpayController wxpayController;
    @Autowired
    private XcxpayController xcxpayController;



    private final Logger logger = LoggerFactory.getLogger(this.getClass());


    @Transactional
    public boolean updateOrderById(Order order){
        return baseMapper.updateById(order)>0;
    }

    /**
     * 分页查找所有的数据
     *
     * @param pageNum  当前页码，从1开始
     * @param pageSize 一页显示多少行
     * @return
     */
    public PageInfo<Order> findAll(int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize,true,false,null);
        List<Order> datas = baseMapper.selectList(null);
        return new PageInfo<Order>(datas);
    }

    /**
     * 分页查找所有用户的订单数据
     *
     * @param pageNum  当前页码，从1开始
     * @param pageSize 一页显示多少行
     * @return
     */
    public PageInfo<Order> getOrderList(Long userId, Integer type, int pageNum, int pageSize) {
        PageHelper.startPage(pageNum, pageSize,true,false,null);
        QueryWrapper<Order> qryWrapper = new QueryWrapper<>();
        qryWrapper.eq("user_id", userId);
        if(type !=null && type >0){
            qryWrapper.eq("type", type);
        }
        List<Order> datas = baseMapper.selectList(null);
        return new PageInfo<Order>(datas);
    }

    public Order findOrderByOrderNo(String orderNo) {
        return baseMapper.findOrderByOrderNo(orderNo);
    }

    public Order findOrderByOutTradeNo(String outTradeNo) {
        QueryWrapper<Order> qryWrapper = new QueryWrapper<>();
        qryWrapper.eq("out_trade_no", outTradeNo);
        return baseMapper.selectOne(qryWrapper);
    }

    public Order findOrderByCollectionOutTradeNo(String outTradeNo) {
        QueryWrapper<Order> qryWrapper = new QueryWrapper<>();
        qryWrapper.eq("collection_out_trade_no", outTradeNo);
        return baseMapper.selectOne(qryWrapper);
    }

    public Order findOrderByFeeOutTradeNo(String outTradeNo) {
        QueryWrapper<Order> qryWrapper = new QueryWrapper<>();
        qryWrapper.eq("fee_out_trade_no", outTradeNo);
        return baseMapper.selectOne(qryWrapper);
    }
    /**
     * 附近订单
     * @param req
     * @return
     */
    public List<OrderNearResp> findNearOrderList(NearOrderReq req,String agentId ,Map<String,String> master,Long userId){
        List<OrderNearResp> resps = new ArrayList<>();
        double lat = Double.parseDouble(req.getLatitude());
        double lon = Double.parseDouble(req.getLongitude());
        List<OrderNear> orderNears = baseMapper.findNearOrderList(lat,lon,req.getDistanceLimit(),Constant.OrderStatusEnum.WAIT_ACCEPT.getCode(),agentId,userId);
        List<OrderNear> nears = new ArrayList<>();
        try {
            if (CollectionUtils.isNotEmpty(orderNears)){
                //类型分组
                Map<String,List<OrderNear>> groupMap = orderNears.
                        parallelStream().
                        collect(Collectors.
                                groupingBy(OrderNear ::getType));
                if (MapUtils.isNotEmpty(master)){
                    master.forEach((k,v)->{
                        List<OrderNear> nearList = groupMap.get(k);
                        if (CollectionUtils.isNotEmpty(nearList)){
                            if (Constant.OrderTypeEnum.PAO_TUI.getCode().toString().equals(k)){
                                nearList.forEach(item->{
                                    nears.add(item);
                                });
                            }else{
                                nearList.forEach(item->{
                                    if (v.contains(item.getChildType())){
                                        nears.add(item);
                                    }
                                });
                            }
                        }
                    });
                }
                if (CollectionUtils.isNotEmpty(nears)){
                    for (OrderNear near:nears) {
                        OrderNearResp resp = new OrderNearResp();
                        BeanUtils.copyProperties(near,resp);
                        getStatusDesc(near.getStatus(),resp);
                        if (near.getHasPartner()!=null&&near.getHasPartner()==1){
                            resp.setOrderTypeDec("合作商家");
                        }else{
                            resp.setOrderTypeDec(getChildTypeOrTypeDesc(near.getType(),near.getChildType(),near.getAgentId()));
                        }
                        if (near.getOrderDate() != null){
                            resp.setOrderDate(DateUtil.dateToString(near.getOrderDate(),"yyyy-MM-dd HH:mm:ss"));
                        }
                        resp.setForecastDeliveryTime(near.getForecastDeliveryTime()!=null?
                                DateUtil.dateToString(near.getForecastDeliveryTime(),DateUtil.FORMAT_ONE):
                                DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                        resp.setTaskTime(near.getTaskTime()!=null?
                                DateUtil.dateToString(near.getTaskTime(),DateUtil.FORMAT_ONE):
                                DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                        resps.add(resp);
                    }
                }
            }
        }catch (Exception ex){
            throw new ServerInternalErrorException(ErrorEnum.ORDER_DETAIL_NOT_EXIST);
        }
        return resps;
    }

    private Boolean getAgentServiceMap(String agentId,String type,String childTypeStrArray){

        return null;
    }

    /**
     * 处理特殊费用
     * 判断处理 节假日、特殊天气、深夜服务三个只能设置一个
     * 如果设置多个取最大
     * @return
     */
    public BigDecimal getSpecialFee(Order order, Map<String,Object> rslt, SysAgent agent, BigDecimal total){
        if(total == null){
            total = BigDecimal.ZERO;
        }
        List<BigDecimal> feeArray = new ArrayList<>();
        List<String> keyArray = new ArrayList<>();

        //1.特殊天气
        if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
            feeArray.add(order.getOtherFee());
            keyArray.add("specialWeatherFee");
        }
        //2.深夜服务费
        if(order.getTaskTime()!=null &&  agent.getNightS() != null && agent.getNightE() !=null &&
                DateUtil.isInTime(order.getTaskTime(), agent.getNightS(),agent.getNightE())){
            //开关
            String switchs = sysParamService.findByNameAndAgent(Constant.SYS_PARAM_FEE_NIGHT_SWITCH,agent.getId());
            if(Constant.SYS_PARAM_SWITCH_ON.equals(switchs)) {
                feeArray.add(agent.getAward());
                keyArray.add("LateNightFee");
            }
        }
        //3.节假日加价
        if(order.getHolidayFee() != null){
            feeArray.add(order.getHolidayFee());
            keyArray.add("HolidayFee");
        }
        if(feeArray.size()>1){
            Optional<BigDecimal> max = feeArray.stream().max((o1, o2) -> o1.compareTo(o2));
            int key = feeArray.indexOf(max.get());
            String maxStr = keyArray.get(key);
            feeArray.clear();
            feeArray.add(max.get());
            keyArray.clear();
            keyArray.add(maxStr);
        }
        if(feeArray.size() == 1 && keyArray.size() == 1){
            switch (keyArray.get(0)){
                case "specialWeatherFee":
                    //1.特殊天气
                    rslt.put("specialWeatherFee", order.getOtherFee());
                    rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
                    total = total.add(order.getOtherFee());
                    //处理已设置值
                    order.setHolidayFee(null);
                    break;
                case "LateNightFee":
                    //2.深夜服务费
                    rslt.put("LateNightFee", agent.getAward());
                    rslt.put("LateNightStart", agent.getNightS());
                    rslt.put("LateNightEnd", agent.getNightE());
                    order.setNightFee(agent.getAward());
                    total = total.add(agent.getAward());
                    //处理已设置值
                    order.setOtherFee(null);
                    order.setOtherFeeInstruction("");
                    order.setHolidayFee(null);
                    break;
                case "HolidayFee":
                    //3.节假日加价
                    rslt.put("HolidayFee", order.getHolidayFee());
                    rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction()==null?"":order.getHolidayFeeInstruction());
                    total = total.add(order.getHolidayFee());
                    //处理已设置值
                    order.setOtherFee(null);
                    order.setOtherFeeInstruction("");
                    break;
                default:
            }
        }
        return total;
    }
    /**
     * 计算订单费用明细及服务费
     * @param order
     * @param agentCategory
     * @return
     */
    public Map<String,Object> calCosts(Order order, SysAgent agent,  SysAgentCategoryCfg agentCategory, Map couponInfo,
                                       AgentServ agentServ, UserPartnerResp user){
        Map<String,Object> rslt = new HashMap<String,Object>();
        BigDecimal total = BigDecimal.ZERO;//总金额
        BigDecimal serviceFee = BigDecimal.ZERO;//运费
        if(Constant.IsOrNotEnum.IS.getCode() == order.getHasPartner()){
            Optional.ofNullable(user).filter(u->user.getIsPartner() == Constant.IsOrNotEnum.IS.getCode())
                    .orElseThrow(()->new ServerInternalErrorException(ErrorEnum.PARTNER_NOT_EXIST));
            //合作商家一键下单
            serviceFee = Optional.ofNullable(user.getPartnerAmount()).orElse(BigDecimal.ZERO)
                    .multiply(new BigDecimal(order.getPartnerNumber()));
            rslt.put("basicFreightFee", serviceFee);
            rslt.put("partnerPerAmount", user.getPartnerAmount());
            rslt.put("partnerNumber", order.getPartnerNumber());
            order.setServiceFee(serviceFee);//保存基础运费（服务费）
            order.setPartnerPerAmount(user.getPartnerAmount());
            //设置基础信息
            order.setType(Constant.OrderTypeEnum.PAO_TUI.getCode());//跑腿
            order.setChildType(Constant.PaotuiTypeEnum.HELP_TAKE.getCode());//帮我送
           /* //1.特殊天气
            if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
                rslt.put("specialWeatherFee", order.getOtherFee());
                rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
                total = total.add(order.getOtherFee());
            }
            //2.深夜服务费
            if(order.getTaskTime()!=null &&  agent.getNightS() != null && agent.getNightE() !=null &&
                    DateUtil.isInTime(order.getTaskTime(), agent.getNightS(),agent.getNightE())){
                rslt.put("LateNightFee", agent.getAward());
                rslt.put("LateNightStart", agent.getNightS());
                rslt.put("LateNightEnd", agent.getNightE());
                order.setNightFee(agent.getAward());
                total = total.add(agent.getAward());
            }
            //3.节假日加价
            if(order.getHolidayFee() != null){
                rslt.put("HolidayFee", order.getHolidayFee());
                rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction());
                total = total.add(order.getHolidayFee());
            }*/
            total = getSpecialFee(order, rslt, agent, total);
        }
        //跑腿
        else if(Constant.OrderTypeEnum.PAO_TUI.getCode() == order.getType()){
            //帮我取//帮我送
            if(Constant.PaotuiTypeEnum.HELP_TAKE.getCode() == order.getChildType() ||
                    Constant.PaotuiTypeEnum.HELP_SEND.getCode() == order.getChildType()){
                //1.订单距离
                Float distance = order.getDistance();
                rslt.put("orderDistance", distance);
                //计算基础运费（服务费）
                serviceFee = cacleServiceFee(order.getDistance(), agentCategory);
                rslt.put("basicFreightFee", serviceFee);
                order.setServiceFee(serviceFee);//保存基础运费（服务费）
                //total.add(serviceFee);
               /* //3.节假日加价
                if(order.getHolidayFee() != null){
                    rslt.put("HolidayFee", order.getHolidayFee());
                    rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction());
                    total = total.add(order.getHolidayFee());
                }
                //4.特殊天气
                if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("specialWeatherFee", order.getOtherFee());
                    rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
                    total = total.add(order.getOtherFee());
                }
                //5.深夜服务费
                if(order.getTaskTime()!=null &&  agent.getNightS() != null && agent.getNightE() !=null &&
                        DateUtil.isInTime(order.getTaskTime(), agent.getNightS(),agent.getNightE())){
                    rslt.put("LateNightFee", agent.getAward());
                    rslt.put("LateNightStart", agent.getNightS());
                    rslt.put("LateNightEnd", agent.getNightE());
                    order.setNightFee(agent.getAward());
                    total = total.add(agent.getAward());
                }*/
                total = getSpecialFee(order, rslt, agent, total);

                //6.保价费用
                if(order.getInsurance() != null && agentCategory != null && agentCategory.getParcelInsuRate()!=null &&
                        order.getInsurance().compareTo(BigDecimal.ZERO) > 0){
                    if(order.getInsurance().compareTo(agentCategory.getParcelInsuBegin())<0){
                        //小于最低保价金额
                        throw new ServerInternalErrorException(ErrorEnum.LESS_THAN_INSURANCE_AMOUNT);
                    }
                    if(order.getInsurance().compareTo(agentCategory.getParcelInsuEnd())>0){
                        //大于最高保价金额
                        throw new ServerInternalErrorException(ErrorEnum.GREATHER_THAN_INSURANCE_AMOUNT);
                    }
                    BigDecimal insuranceFee = order.getInsurance().multiply(agentCategory.getParcelInsuRate().divide(new BigDecimal(100)));
                    insuranceFee = insuranceFee.setScale(2, BigDecimal.ROUND_HALF_UP);
                    order.setInsuranceFee(insuranceFee);//保存保价手续费
                    rslt.put("insuranceFee", insuranceFee);
                    rslt.put("insuranceRate", agentCategory.getParcelInsuRate());
                    total = total.add(insuranceFee);
                }
                //7.代收款手续费
               /* if(order.getCollectionAmount() != null && agentCategory.getCollectingServiceRate() != null &&
                        order.getCollectionAmount().compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal collectionFee = order.getCollectionAmount().multiply(agentCategory.getCollectingServiceRate().divide(new BigDecimal(100)));
                    collectionFee = collectionFee.setScale(2, BigDecimal.ROUND_HALF_UP);
                    order.setCollectionFee(collectionFee);//保存代收款手续费
                    rslt.put("collectionFee", collectionFee);
                    rslt.put("collectionRate", agentCategory.getCollectingServiceRate());
                    total = total.add(collectionFee);
                }*/
               //代收款统一提现时收取提现手续费

                //8.超重费用
                if(order.getWeight() != null && order.getWeight() > 0 &&agentCategory !=null  && agentCategory.getWeightEnd()!=null
                        && agentCategory.getWeightExtraPrice() !=null && order.getWeight() > agentCategory.getWeightBegin()){
                    if(order.getWeight() > agentCategory.getWeightEnd()){
                        //未开通的服务类型
                        throw new ServerInternalErrorException(ErrorEnum.WEIGHT_OVER_MAX);
                    }
                    BigDecimal overWeightFee = agentCategory.getWeightExtraPrice().multiply(new BigDecimal(order.getWeight()-agentCategory.getWeightBegin()));
                    overWeightFee = overWeightFee.setScale(2, BigDecimal.ROUND_HALF_UP);
                    rslt.put("overWeightFee", overWeightFee);
                    rslt.put("overWeightPrice", agentCategory.getWeightExtraPrice());
                    rslt.put("overWeightBegin", agentCategory.getWeightBegin());
                    rslt.put("overWeightEnd", agentCategory.getWeightEnd());
                    total = total.add(overWeightFee);
                    order.setOverweightFee(overWeightFee);//保存
                }
                if(agentCategory != null){
                    order.setCategoryName(agentCategory.getCategory());
                }
            //随意购
            }else if(Constant.PaotuiTypeEnum.ANY_BUY.getCode() == order.getChildType()){
                //商品费用
                if(order.getGoodsAmount() != null && order.getGoodsAmount().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("goodsAmount", order.getGoodsAmount());
                    total = total.add(order.getGoodsAmount());
                }
                if(order.getFromAddressId() == null || order.getFromAddressId() == 0){
                    //附近购买，只收取起步费
                    serviceFee = serviceFee.add(agentCategory.getInitiatePrice());
                    rslt.put("basicFreightFee", serviceFee);
                    order.setServiceFee(serviceFee);//保存基础运费（服务费）
                    rslt.put("orderDistance", order.getDistance());
                }else{
                    //有购买地址
                    //1.订单距离
                    Float distance = order.getDistance();
                    if(distance == null || distance == 0f){
                        //起始地址可以相同
                        if(order.getFromAddressId() != null && order.getToAddressId() != null
                                && !order.getFromAddressId().equals(order.getToAddressId())){
                            //throw new ServerInternalErrorException(ErrorEnum.ORDER_INFO_NOT_INCOMPLETE);
                        }
                    }
                    rslt.put("orderDistance", distance);
                    //计算基础运费（服务费）
                    serviceFee = cacleServiceFee(order.getDistance(), agentCategory);
                    rslt.put("basicFreightFee", serviceFee);
                    order.setServiceFee(serviceFee);//保存基础运费（服务费）
                }
                //特殊费用
                total = getSpecialFee(order, rslt, agent, total);

                if(agentCategory != null){
                    order.setCategoryName(agentCategory.getCategory());
                }
            }else{
                //未开通的服务类型
                throw new ServerInternalErrorException(ErrorEnum.SERVICE_TYPE_NOT_EXIST);
            }
            //万能帮办
       // }else if(Constant.OrderTypeEnum.ANY_HELP.getCode() == order.getType()){
        }else if(order.getType() != null){
            if(agentServ == null){
                //未开通的服务类型
                throw new ServerInternalErrorException(ErrorEnum.SERVICE_TYPE_NOT_EXIST);
            }
            //Integer orderChildType = order.getChildType();//万能帮办子类型
            if(Constant.PriceWayEnum.SURE_PRICE.getCode() == agentServ.getPriceWay()){
                //定价
                rslt.put("anyHelpFee", agentServ.getFee());
                rslt.put("onSiteServiceFee", BigDecimal.ZERO);
                total = total.add(agentServ.getFee());
                order.setAnyhelpFee(agentServ.getFee());//上门费包含在内
                order.setPriceWay(Constant.PriceWayEnum.SURE_PRICE.getCode());
            }else{
                //不定价 此时保存的上门费用
                rslt.put("anyHelpFee", BigDecimal.ZERO);
                rslt.put("onSiteServiceFee", agentServ.getFee());//
                total = total.add(agentServ.getFee());
                //order.setAnyhelpFee(agentServ.getFee());//师傅完成时补录
                order.setOnsiteFee(agentServ.getFee());//上门费用
                order.setPriceWay(Constant.PriceWayEnum.NOT_SURE_PRICE.getCode());
            }
        }else{
            //未开通的服务类型
            throw new ServerInternalErrorException(ErrorEnum.SERVICE_TYPE_NOT_EXIST);
        }
        //3.优惠券抵扣 //保存订单时消费优惠券
        if(order.getCouponId() != null && couponInfo != null){
            Integer couponType = (Integer)couponInfo.get("type");
            BigDecimal couponAmt = (BigDecimal)couponInfo.get("amount");//优惠券金额
            if(couponType == Constant.CouponType.FULL_CUT){
                //满减券
                BigDecimal minGoodsAmt = (BigDecimal)couponInfo.get("min_goods_amount");//满减金额
                if(total.compareTo(minGoodsAmt) >= 0){
                    total = total.subtract(couponAmt);
                    rslt.put("coupon", couponAmt);
                    order.setCouponAmount(couponAmt);
                }else{
                    rslt.put("coupon", BigDecimal.ZERO);
                    order.setCouponAmount(BigDecimal.ZERO);
                }
                String desc = "满"+minGoodsAmt+"减"+couponAmt;
                rslt.put("couponType", desc);
                order.setCouponDesc(desc);
            }else if(couponType == Constant.CouponType.OUTRIGHT){
                //立减券
                total = total.subtract(couponAmt);
                order.setCouponAmount(couponAmt);
               /* if(total.compareTo(BigDecimal.ZERO) <= 0){
                    total = BigDecimal.ZERO;
                }*/
                rslt.put("coupon", couponAmt);
                String desc = "立减"+couponAmt;
                rslt.put("couponType", desc);
            }
            if(total.compareTo(BigDecimal.ZERO) <= 0){
                total = BigDecimal.ZERO;
            }
        }
        //8.总金额
        //计算优惠券后再累加运费
        total = total.add(serviceFee);
        //total = new BigDecimal(0.01);//测试用
        rslt.put("totalAmt", total);
        order.setAmount(total);
        return rslt;
    }

    /**
     * 计算基础运费
     * @param distance 订单距离
     * @param agentCategory 分类配置
     * @return 基础运费
     */
    public BigDecimal cacleServiceFee(Float distance, SysAgentCategoryCfg agentCategory){
        BigDecimal serviceFee = BigDecimal.ZERO;//运费
        BigDecimal distanceNew = BigDecimal.ZERO;//订单距离
        //2.基础运费 ：x+m（y+z）（x是3公里起步价，m是总距离-3公里，y是3公里外的每公里的单价，z是超出10公里外的总距离（-3公里）每公里额外加价）。公里数可设置。
        if(distance != null){
            distanceNew = new BigDecimal(distance);
        }
        if(agentCategory != null && agentCategory.getInitiatePrice() != null){
            //检查是否配置基础运费
            serviceFee = serviceFee.add(agentCategory.getInitiatePrice());
        }
        //检查必要配置
        if(agentCategory != null && agentCategory.getInitiateKm() != null
                && agentCategory.getExceedExtraPrice() != null && agentCategory.getOverInitKmPrice() != null) {
            BigDecimal otherDistance = distanceNew.subtract(agentCategory.getInitiateKm());//减去起步里程剩余里程
            BigDecimal exceedExtraPrice = BigDecimal.ZERO;//大于超出里程的单价
            if (otherDistance.compareTo(BigDecimal.ZERO) <= 0) {
                otherDistance = BigDecimal.ZERO;
            } else if (distanceNew.compareTo(agentCategory.getExceedKm()) > 0) {
                exceedExtraPrice = agentCategory.getExceedExtraPrice();
                BigDecimal tempPrice = exceedExtraPrice.add(agentCategory.getOverInitKmPrice());
                serviceFee = serviceFee.add(otherDistance.multiply(tempPrice));
                serviceFee = serviceFee.setScale(2, BigDecimal.ROUND_HALF_UP);
            } else {
                serviceFee = serviceFee.add(otherDistance.multiply(agentCategory.getOverInitKmPrice()));
                serviceFee = serviceFee.setScale(2, BigDecimal.ROUND_HALF_UP);
            }
        }
        return serviceFee;
    }


    /**
     * 查询订单费用明细及服务费
     * @param order
     * @param agentCategory
     * @return
     */
    public Map<String,Object> queryCosts(Order order, SysAgent agent,  SysAgentCategoryCfg agentCategory,
                                       AgentServ agentServ){
        Map<String,Object> rslt = new HashMap<String,Object>();
        BigDecimal total = order.getAmount();//总金额
        BigDecimal serviceFee = BigDecimal.ZERO;//运费
        if(Constant.IsOrNotEnum.IS.getCode() == order.getHasPartner()){
            rslt.put("basicFreightFee", order.getServiceFee());
            rslt.put("partnerPerAmount", order.getPartnerPerAmount());
            rslt.put("partnerNumber", order.getPartnerNumber());
            //1.特殊天气
            if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
                rslt.put("specialWeatherFee", order.getOtherFee());
                rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
            }
            //2.深夜服务费
            if(order.getNightFee() != null){
                rslt.put("LateNightFee", order.getNightFee());
                rslt.put("LateNightStart", agent.getNightS());
                rslt.put("LateNightEnd", agent.getNightE());
            }
            //3.节假日加价
            if(order.getHolidayFee() != null){
                rslt.put("HolidayFee", order.getHolidayFee());
                rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction());
            }
        }
        //跑腿
        else if(Constant.OrderTypeEnum.PAO_TUI.getCode() == order.getType()){
            //帮我取//帮我送
            if(Constant.PaotuiTypeEnum.HELP_TAKE.getCode() == order.getChildType() ||
                    Constant.PaotuiTypeEnum.HELP_SEND.getCode() == order.getChildType()){
                //1.订单距离
                Float distance = order.getDistance();
                rslt.put("orderDistance", distance);
                //计算基础运费（服务费）
                rslt.put("basicFreightFee", order.getServiceFee());
                //3.节假日加价
                if(order.getHolidayFee() != null){
                    rslt.put("HolidayFee", order.getHolidayFee());
                    rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction());
                }
                //4.特殊天气
                if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("specialWeatherFee", order.getOtherFee());
                    rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
                }
                //5.深夜服务费
                if(order.getNightFee()!=null ){
                    rslt.put("LateNightFee", order.getNightFee());
                    rslt.put("LateNightStart", agent.getNightS());
                    rslt.put("LateNightEnd", agent.getNightE());
                }
                //6.保价费用
                if(order.getInsurance() != null && agentCategory.getParcelInsuRate()!=null &&
                        order.getInsurance().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("insuranceFee", order.getInsuranceFee());
                    rslt.put("insuranceRate", agentCategory.getParcelInsuRate());
                }
                //7.代收款手续费//代收款统一提现收手续费
             /*   if(order.getCollectionAmount() != null && agentCategory.getCollectingServiceRate() != null &&
                        order.getCollectionAmount().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("collectionFee", order.getCollectionFee());
                    rslt.put("collectionRate", agentCategory.getCollectingServiceRate());
                }*/
                //8.超重费用
                if(order.getWeight() != null && order.getWeight() > 0 &&agentCategory.getWeightEnd()!=null
                        && agentCategory.getWeightExtraPrice() !=null && order.getWeight() > agentCategory.getWeightBegin()){
                    rslt.put("overWeightFee", order.getOverweightFee());
                    rslt.put("overWeightPrice", agentCategory.getWeightExtraPrice());
                    rslt.put("overWeightBegin", agentCategory.getWeightBegin());
                    rslt.put("overWeightEnd", agentCategory.getWeightEnd());
                }
                //随意购
            }else if(Constant.PaotuiTypeEnum.ANY_BUY.getCode() == order.getChildType()){
                //商品费用
                if(order.getGoodsAmount() != null && order.getGoodsAmount().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("goodsAmount", order.getGoodsAmount());
                }
                if(order.getFromAddressId() == null || order.getFromAddressId() == 0){
                    //附近购买，只收取起步费
                    rslt.put("basicFreightFee", order.getServiceFee());
                    rslt.put("orderDistance", order.getDistance());
                }else{
                    //有购买地址
                    //1.订单距离
                    Float distance = order.getDistance();
                    rslt.put("orderDistance", order.getDistance());
                    //计算基础运费（服务费）
                    rslt.put("basicFreightFee", order.getServiceFee());
                }
                //3.节假日加价
                if(order.getHolidayFee() != null){
                    rslt.put("HolidayFee", order.getHolidayFee());
                    rslt.put("HolidayFeeInfo", order.getHolidayFeeInstruction());
                }
                //4.特殊天气
                if(order.getOtherFee() != null && order.getOtherFee().compareTo(BigDecimal.ZERO) > 0){
                    rslt.put("specialWeatherFee", order.getOtherFee());
                    rslt.put("specialWeatherInfo", order.getOtherFeeInstruction());
                }
                //5.深夜服务费
                if(order.getNightFee()!=null ){
                    rslt.put("LateNightFee", order.getNightFee());
                    rslt.put("LateNightStart", agent.getNightS());
                    rslt.put("LateNightEnd", agent.getNightE());
                }
            }
            //万能帮办
        //}else if(Constant.OrderTypeEnum.ANY_HELP.getCode() == order.getType()){
        }else{
            //Integer orderChildType = order.getChildType();//万能帮办子类型
            if(Constant.PriceWayEnum.SURE_PRICE.getCode() == agentServ.getPriceWay()){
                //定价
                rslt.put("anyHelpFee", order.getAnyhelpFee());
                rslt.put("onSiteServiceFee", BigDecimal.ZERO);
            }else{
                //不定价 此时保存的上门费用
                BigDecimal anyHelpFee = new BigDecimal(0.00);
                if(order.getAnyhelpFee() != null){
                    anyHelpFee = order.getAnyhelpFee();
                }
                rslt.put("onSiteServiceFee", order.getOnsiteFee());//
                rslt.put("anyHelpFee", anyHelpFee);
                total= total.add(anyHelpFee);
            }
        }
        //3.优惠券抵扣 //保存订单时消费优惠券
        if(order.getCouponId() != null){
            rslt.put("coupon", order.getCouponAmount());
            rslt.put("couponType", order.getCouponDesc());
        }
        //8.总金额
        rslt.put("totalAmt", total);
        return rslt;
    }

    /**
     * 已接订单/完成订单
     * @param userId
     * @return
     */
    public List<OrderNearResp> getOrderByStatus(Long userId, Integer status, String orderNo){
        List<OrderNearResp> resps = new ArrayList<>();
        List<OrderNear> orderNears = baseMapper.findOrderByStatus(status,userId,orderNo,null);
        try {
            if (CollectionUtils.isNotEmpty(orderNears)){
                for (OrderNear near:orderNears) {
                    OrderNearResp resp = new OrderNearResp();
                    BeanUtils.copyProperties(near,resp);
                    resp.setForecastDeliveryTime(near.getForecastDeliveryTime()!=null?
                                    DateUtil.dateToString(near.getForecastDeliveryTime(),DateUtil.FORMAT_ONE):
                            DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                    if (near.getHasPartner()!=null
                            &&near.getHasPartner()==1){
                        resp.setOrderTypeDec("合作商家");
                    }else{
                        resp.setOrderTypeDec(getChildTypeOrTypeDesc(near.getType(),near.getChildType(),near.getAgentId()));

                    }
                    resp.setTaskTime(near.getTaskTime()!=null?
                            DateUtil.dateToString(near.getTaskTime(),DateUtil.FORMAT_ONE):
                            DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                    resp.setOrderDate(DateUtil.dateToString(near.getOrderDate(),DateUtil.FORMAT_ONE));
                    resps.add(resp);
                }
            }
        }catch (Exception ex){
            throw new ServerInternalErrorException(ErrorEnum.VERIFY_CODE_VALID_ERROR);
        }
        return resps;
    }


    /**
     *  分页查找所有的数据
     * @param pageNum 当前页码，从1开始
     * @param pageSize  一页显示多少行
     * @param type
     * @return
     */
    public PageInfo<OrderSimple> queryAllOrders(Long userId,Integer status, Integer type, int pageNum, int pageSize, String agentId) {
        PageHelper.startPage(pageNum, pageSize,true,false,null);
        List<OrderSimple> datas = baseMapper.findAllOrders(status, userId, type, agentId);
        return new PageInfo<OrderSimple>(datas);
    }

    /**
     *  按id查找订单
     * @return
     */
    public OrderMore queryOrderById(Long id) {
        OrderMore datas = baseMapper.findOrderById(id);
        return datas;
    }

    /**
     * 师傅title明细
     * @param userId
     * @return
     */
    public MasterTitleMessageResp  getMasterDetail(Long userId,List<Integer> status,MasterTitleMessageResp resps){
        List<OrderNear> orderNears = baseMapper.findOrderByStatusList(status,userId);
        String count = StringUtils.EMPTY+0;
        //今日已完成订单数
        if (CollectionUtils.isNotEmpty(orderNears)){
            count = orderNears.size()+"";
        }
        resps.setOrderNum(count);
        return resps;
    }

    public List<OrderNear>  getOrderByStatusList(Long userId,List<Integer> statusList){
        return baseMapper.findOrderByStatusList(statusList,userId);
    }

    public List<OrderNear> findOrderByStatusListCurDate(Long userId,List<Integer> statusList,Date date){
        return baseMapper.findOrderByStatusListCurDate(statusList,userId,date ==null?null:DateUtil.dateToString(date,"yyyy-MM-dd"));
    }

    /**
     * 查找订单
     * @param status
     * @param userId
     * @param orderNo
     * @param dateFlag
     * @return
     */
    public List<OrderNear> findOrderByStatus(Integer status, Long userId, String orderNo, String dateFlag){
        List<OrderNear> orderNears = baseMapper.findOrderByStatus(status,userId,orderNo,dateFlag);
        return orderNears;
    }

    /**
     * 查找订单（分页）
     * @param status
     * @param userId
     * @return
     */
    public PageInfo<OrderNearResp> findOrderByStatusPage(List<Integer>status,Long userId,Integer pageNum,Integer pageSize){
        PageHelper.startPage(pageNum, pageSize,true,false,null);
        List<OrderNear> orderNears = baseMapper.findOrderByStatusList(status,userId);
        List<OrderNearResp> nearResps = new ArrayList<>();
        try {
            if (CollectionUtils.isNotEmpty(orderNears)){
                for (OrderNear near:orderNears){
                    OrderNearResp nearResp = new OrderNearResp();
                    BeanUtils.copyProperties(near,nearResp);
                    getStatusDesc(near.getStatus(),nearResp);
                    if (near.getOrderDate()!= null){
                        nearResp.setOrderDate(DateUtil.dateToString(near.getOrderDate(),"yyyy-MM-dd HH:mm:ss"));
                    }
                    if (StringUtils.isNotEmpty(near.getType())){
                        String childTypeDesc = StringUtils.EMPTY;
                        if (near.getHasPartner()!=null
                                &&near.getHasPartner()==1){
                            childTypeDesc = "合作商家";
                        }else{
                            childTypeDesc = getChildTypeOrTypeDesc(near.getType(),near.getChildType(),near.getAgentId());

                        }
                        nearResp.setOrderTypeDec(childTypeDesc);
                    }
                    nearResp.setForecastDeliveryTime(near.getForecastDeliveryTime()!=null?
                            DateUtil.dateToString(near.getForecastDeliveryTime(),DateUtil.FORMAT_ONE):
                            DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                    nearResp.setTaskTime(near.getTaskTime()!=null?
                            DateUtil.dateToString(near.getTaskTime(),DateUtil.FORMAT_ONE):
                            DateUtil.dateToString(new Date(),DateUtil.FORMAT_ONE));
                    nearResps.add(nearResp);
                }
            }
        }catch (Exception ex){
            throw new ServerInternalErrorException(ex.getMessage());
        }

        return new PageInfo<OrderNearResp>(nearResps);
    }

    /**
     * 检查师傅已接订单是否超过5单
     * @param masterId
     * @return
     */
    public Boolean checkDoingCount(Long masterId){
        List<Integer> statusList = new ArrayList<>();
        statusList.add(Constant.OrderStatusEnum.SERVERING.getCode());
        statusList.add(Constant.OrderStatusEnum.FETCHING.getCode());
        statusList.add(Constant.OrderStatusEnum.SENDING.getCode());
        List<OrderNear> orderNears = baseMapper.findOrderByStatusList(statusList,masterId);

        //获取师傅最大接单笔数
        QueryWrapper<SysParam> query = new QueryWrapper<>();
        query.eq("name","MASTER_ORDER_LIMIT");
        SysParam param = sysParamService.getOne(query);
        int maxCnt = 5;//默认5
        if(param != null ){
            maxCnt = Integer.parseInt(param.getValue());
        }
        if(maxCnt == 0){
            maxCnt = 5 ;
        }

        if(orderNears.size()< maxCnt){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 检查师傅已接订单是否超过5单
     * @return
     */
    public Boolean checkRefuse(Integer orderId,Long masterId){
        List<OrderDispatch> list = orderDispatchService.findRefuse(orderId);
        for(OrderDispatch od:list){
            if(masterId.equals( od.getMasterId())){
                return false;
            }
        }
        return true;
    }

    /**
     * 检查师傅技能是否匹配
     * @return
     */
    public Boolean checkMasterSkill(MasterWaitResp master, OrderSimple order){
        //查询订单类型匹配的师傅
        Map mapTypes = JSON.parseObject(master.getSkillType());
        if(mapTypes == null || mapTypes.size() == 0){
            return false;
        }
        logger.error("检查师傅技能是否匹配：",order.getOrderNo(),",订单类型：",order.getOrderType(),",订单子类型：",order.getOrderChildType(),",师傅技能：",master.getSkillType());
        /*for (Object obj : mapTypes.keySet()){
            logger.error("key为："+obj+"值为："+mapTypes.get(obj));
        }*/
        if(mapTypes.containsKey(order.getOrderType().toString())){
            String tempChildType = (String)mapTypes.get(order.getOrderType());
            //if(type.equals("1") || (tempChildType != null && tempChildType.indexOf(childType)>=0)){
            if( "1".equals(order.getOrderType().toString()) ||((tempChildType != null && tempChildType.indexOf(order.getOrderChildType())>=0)) ){
                logger.error("匹配");
                return true;
            }
        }
        logger.error("不匹配");
        return false;
    }

    @Transactional
    public Boolean userCancelOrder(String orderNo,String decidedFlag){
        try {
            if (StringUtils.isEmpty(orderNo)){
                throw new ServerInternalErrorException(ErrorEnum.ORDER_NO_EMPTY);
            }
            if (StringUtils.isEmpty(decidedFlag)){
                throw new ServerInternalErrorException(ErrorEnum.ORDER_DECIDED_EMPTY);

            }
            Order order = baseMapper.findOrderByOrderNo(orderNo);
            switch (decidedFlag){
                case MasterConstants.YSS:
                    order.setStatus(8);
                    order.setDeleteState(1);
                    order.setId(null);
                    baseMapper.insert(order);
                    break;
                case MasterConstants.DICPATCH:
                    order.setStatus(2);
                    order.setMasterId(null);
                    baseMapper.updateById(order);
                    break;
                default:
                    break;
            }
            return true;
        }catch (Exception ex){
            if (ex instanceof ServerInternalErrorException){
                throw new ServerInternalErrorException(ex.getMessage());
            }
            throw new ServerInternalErrorException(ErrorEnum.ORDER_UPDATE_ERROR);
        }
    }


    public HistoryOrderResp getHistoryOrderNum(Long userId){
        HistoryOrderResp orderResp = new HistoryOrderResp();
        List<Integer> statList = new ArrayList<>();
        statList.add(Constant.OrderStatusEnum.OK.getCode());
        statList.add(Constant.OrderStatusEnum.CANCLE.getCode());
        statList.add(Constant.OrderStatusEnum.WAIT_EVLAUTE.getCode());
        List<OrderNear> ord = baseMapper.findOrderByStatusList(statList,userId);
        Integer currentWeekNum = baseMapper.currentWeekNum(statList,userId);
        Integer currentMonthNum = baseMapper.currentMonthNum(statList,userId);
        if (CollectionUtils.isNotEmpty(ord)){
            orderResp.setCountNum(String.valueOf(ord.size()));
            orderResp.setCurrentWeekNum(String.valueOf(currentWeekNum));
            orderResp.setCurrentMonthNum(String.valueOf(currentMonthNum));
        }else{
            orderResp.setCurrentWeekNum("0");
            orderResp.setCurrentMonthNum("0");
            orderResp.setCountNum("0");
        }
        return orderResp;
    }

    public String getChildTypeOrTypeDesc(String key,String childType,String agentId){
        if (key.equals(Constant.OrderTypeEnum.PAO_TUI.getCode().toString())){
            List<Dict> dicts = DictUtil.getChildren("SERVICE_PAOTUI");
            if (CollectionUtils.isNotEmpty(dicts)){
                for (Dict dict : dicts) {
                    if (dict.getCode().equals(childType)){
                        return dict.getValue();
                    }
                }
            }
        }else{
            AgentServ agentServ =  agentServService.queryServByAgentIdAndCode(agentId,key,childType);
            if (agentServ!=null){
                return agentServ.getServiceName();
            }
        }
        return StringUtils.EMPTY;
    }


    private void getStatusDesc(Integer status,OrderNearResp nearResp){
        if (status== Constant.OrderStatusEnum.WAIT_ACCEPT.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.WAIT_ACCEPT.getMessage());
        }else if (status== Constant.OrderStatusEnum.WAIT_PAY.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.WAIT_PAY.getMessage());

        }else if (status== Constant.OrderStatusEnum.WAIT_EVLAUTE.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.WAIT_EVLAUTE.getMessage());

        }else if (status== Constant.OrderStatusEnum.OK.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.OK.getMessage());

        }else if (status== Constant.OrderStatusEnum.CANCLE.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.CANCLE.getMessage());

        }else if (status== Constant.OrderStatusEnum.FETCHING.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.FETCHING.getMessage());

        }else if (status== Constant.OrderStatusEnum.SENDING.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.SENDING.getMessage());

        }else if (status== Constant.OrderStatusEnum.SERVERING.getCode()){
            nearResp.setStatusdesc(Constant.OrderStatusEnum.SERVERING.getMessage());

        }
    }

    /**
     * 更新订单状态
     * @return
     */
    public int updateOrderStatus(){
        UpdateWrapper<Order> updateWrapper = new UpdateWrapper<>();
        Order order = new Order();
        order.setStatus(Constant.OrderStatusEnum.CANCLE.getCode());
        order.setCancleTime(new Date());
        order.setCancleBy(1);//系统取消
        updateWrapper.ge("(unix_timestamp(now())-unix_timestamp(create_at))/60", 30);
        updateWrapper.eq("status", Constant.OrderStatusEnum.WAIT_PAY.getCode());
        return baseMapper.update(order,updateWrapper);
    }

    /**
     *  查找所有的数据
     * @param type
     * @return
     */
    public List<OrderSimple> queryAllOrdersNoPage(Long userId, Integer status, Integer type, String agentId) {
        List<OrderSimple> datas = baseMapper.findAllOrders(status, userId, type, agentId);
        return datas;
    }

    /**
     * 超过30分钟未接单取消订单，退款到余额
     */
    public int cancleByUnAccept(){
        QueryWrapper<Order> updateWrapper = new QueryWrapper<>();
        updateWrapper.ge("(unix_timestamp(now())-unix_timestamp(update_at))/60", 30);
        updateWrapper.eq("status", Constant.OrderStatusEnum.WAIT_ACCEPT.getCode());
        List<Order> orders = baseMapper.selectList(updateWrapper);
        if(orders != null && orders.size() > 0){
            orders.stream().forEach(order -> {
                //查询当前订单的流程状态
                BigDecimal orderAmount = order.getAmount();
                User master = userService.getById(order.getMasterId());
                //处理优惠券
                if(order.getCouponId() !=null && order.getCouponAmount() !=null){
                    //优惠券还原成未使用状态
                    UserCoupon userCoupon = userCouponService.getById(order.getCouponId());
                    if(userCoupon != null ){
                        userCoupon.setState(Integer.parseInt(Constant.COUPON_STATUS_NOT_USED));
                        if(userCouponService.updateById(userCoupon)){
                            orderAmount = orderAmount.subtract(order.getCouponAmount());
                        }
                    }
                }
                if(orderAmount.compareTo(BigDecimal.ZERO) > 0) {
                    //修改用户余额
                    User user = userService.getById(order.getUserId());
                    Optional.ofNullable(order).orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.USER_NOT_EXISTS));
                    BigDecimal balance = Optional.ofNullable(orderAmount).orElse(BigDecimal.ZERO).add(user.getAccountBalance());
                    user.setAccountBalance(balance);
                    if (userService.updateById(user)) {
                        //保存余额变动明细
                        UserAccountDetail userAccountDetail = new UserAccountDetail();
                        userAccountDetail.setAccountType("1");
                        userAccountDetail.setAccoutWay(1L);
                        userAccountDetail.setAmount(order.getAmount().toString());
                        userAccountDetail.setCreateDt(new Date());
                        userAccountDetail.setDetailType("2");
                        userAccountDetail.setInOutType("1");
                        userAccountDetail.setTranDesc("订单退款:" + order.getOrderNo());
                        userAccountDetail.setUserId(order.getUserId());
                        userAccountDetail.setStatus("0");
                        detailService.save(userAccountDetail);
                        //修改订单状态
                        order.setStatus(Constant.OrderStatusEnum.CANCLE.getCode());
                        order.setUpdateAt(new Date());
                        order.setCancleTime(new Date());
                        order.setCancleBy(1);//系统取消
                        baseMapper.updateById(order);
                    } else {
                        System.out.println("用户取消订单[%s],用户余额变动失败:" + order.getOrderNo());
                    }
                }
                //全额优惠券抵扣的情况

                //派单
                OrderDispatch orderDispatch = orderDispatchService.getByOrderId(order.getId());
                if(orderDispatch !=null){
                    orderDispatch.setStatus(4);//状态 1-待接单 2-已接单 3-已拒绝 4-已取消
                    orderDispatchService.saveOrUpdate(orderDispatch);
                }
            });
        }
        return orders.size();
    }

    /**
     * 地址完整性校验
     */
    public void valideAddress(Order order){
        /*//跑腿需要校验类别
        if(Constant.OrderTypeEnum.PAO_TUI.getCode() == order.getType()){
            //跑腿-随意购
            if((Constant.PaotuiTypeEnum.ANY_BUY.getCode() == order.getChildType())){

                throw new ServerInternalErrorException(ErrorEnum.NO_FROM_ADDRESS);
            }else{

            }
        }else{
            //校验地址完整性
            if(order.getFromAddressId() != null && order.getFromAddressId() > 0l){

            }
        }*/
        //跑腿-任意购起始地址不校验完整性
        if(Constant.OrderTypeEnum.PAO_TUI.getCode() == order.getType() &&
                Constant.PaotuiTypeEnum.ANY_BUY.getCode() == order.getChildType() &&
                order.getFromAddressId() != null  ){

        }else{
            //校验地址完整性
            if(order.getFromAddressId() != null && order.getFromAddressId() > 0l){
                Address ad  = addressService.getById(order.getFromAddressId());
                Optional.ofNullable(ad).orElseThrow(() ->new ServerInternalErrorException(ErrorEnum.NO_FROM_ADDRESS));
                if(StringUtils.isEmpty(ad.getName()) || StringUtils.isEmpty(ad.getPhone())){
                    throw new ServerInternalErrorException(ErrorEnum.ADDRESS_NOT_COMPLETE);
                }
            }
            if(order.getToAddressId() != null && order.getToAddressId() > 0l){
                Address ad  = addressService.getById(order.getToAddressId());
                Optional.ofNullable(ad).orElseThrow(() ->new ServerInternalErrorException(ErrorEnum.NO_FROM_ADDRESS));
                if(StringUtils.isEmpty(ad.getName()) || StringUtils.isEmpty(ad.getPhone())){
                    throw new ServerInternalErrorException(ErrorEnum.ADDRESS_NOT_COMPLETE);
                }
            }
        }
    }


    /**
     * 查找所有订单
     * 根据状态
     * @return
     */
    public List<Order> queryOrders(Integer status) {
        QueryWrapper<Order> qryWrapper = new QueryWrapper<>();
        qryWrapper.eq("status", status);
        return baseMapper.selectList(qryWrapper);
    }

    /**
     * 在语音提醒3次，电话语音两次后
     * 1. 自动派单改派两次
     * 2. 其他判断是否到订单自动取消时间，已到时间取消
     */
    public int changeDispatchOrCancle() {
        List<Order> list = this.queryOrders(Constant.OrderStatusEnum.WAIT_ACCEPT.getCode());
        int count = 0;
        for(int i=0;i<list.size();i++){
            Order order = list.get(i);
            if(order == null){
                continue;
            }
            //查询派单类型
            SysAgent agent = agentServices.getById(order.getAgentId());

            int tempTime = 30;//分钟
            if(order.getType() == Constant.OrderTypeEnum.PAO_TUI.getCode()){
                tempTime = agent.getPaotuiCtime();
            }else{
                tempTime = agent.getOtherCtime();
            }
            if(tempTime<= 0){
                tempTime = 30*60;
            }else{
                tempTime = tempTime * 60;
            }
            int tempOrderTime = (int)DateUtil.timeSubSec(order.getCreateAt(),new Date());
            //超过自动取消时间，取消订单
            if(tempOrderTime > tempTime){
                if("auto".equals(agent.getDispatchType())){
                    List<OrderDispatch> refuseList = orderDispatchService.findRefuse(order.getId().intValue());
                    int countChange = agent.getAutoCount();
                    if(tempTime<= 0){
                        countChange = 2+1;
                    }else{
                        countChange = countChange+1;
                    }
                    //第一个师傅未接单时，改派2次，如果未接单取消
                    if(refuseList.size()>=countChange){
                        //超过自动取消时间，取消订单
                        if(cancleOrder(order, true)){
                            count++;
                        }
                    }
                }else{
                    //人工和抢单
                    if(cancleOrder(order,true)){
                        count++;
                    }
                }
            }else{
                //判断是否自动派单，且未接单，改派两次
                //if(!"auto".equals(agent.getDispatchType())){
                //    continue;
               // }
                //派单
                OrderDispatch orderDispatch = orderDispatchService.getByOrderId(order.getId());
                if(orderDispatch != null && orderDispatch.getCallCount() >= 2 && orderDispatch.getPushCount() >=1 ){
                    long time = (new Date().getTime() - orderDispatch.getCreateAt().getTime())/1000;
                    if(time>=300){
                        //5分钟未接单，订单重回订单池重新派单
                        orderDispatch.setStatus(3);//状态 1-待接单 2-已接单 3-已拒绝
                        orderDispatchService.saveOrUpdate(orderDispatch);
                    }
                }

            }
        }
        return count;
    }

    /**
     * 取消订单
     * @param order
     * @return
     */
    @Transactional
    public boolean cancleOrder(Order order, boolean isAuto){
        Integer tempStatus = order.getStatus();
        //查询当前订单的流程状态
        MasterOrderAccitity accitity = accitityService.getMasterAccitityByOrderId(order.getId(), null);
        BigDecimal orderAmount = order.getAmount();
        User master = userService.getById(order.getMasterId());
        //处理优惠券
        if(order.getCouponId() !=null && order.getCouponAmount() !=null){
            //优惠券还原成未使用状态
            UserCoupon userCoupon = userCouponService.getById(order.getCouponId());
            if(userCoupon != null ){
                userCoupon.setState(Integer.parseInt(Constant.COUPON_STATUS_NOT_USED));
                if(userCouponService.updateById(userCoupon)){
                    orderAmount = orderAmount.subtract(order.getCouponAmount());
                }
            }
        }
        if(orderAmount.compareTo(BigDecimal.ZERO) <= 0){
            //全额优惠券抵扣的情况
            return true;
        }
        //flag  是否扣款
        boolean  flag = false;
        /*
         * 需要扣款 的节点：
         * 帮我送：我已到达（第二步完成）
         * 帮我取：我已到达
         * 随意购：我已到达（附近购买以终点我已到达为判断依据）
         * 万能帮办：第三步拍照完毕，开始服务为节点
         * 按比例扣除后师傅和分站平分
         *
         */
        if(order.getType() == Constant.OrderTypeEnum.PAO_TUI.getCode() && accitity !=null){
            //跑腿
            if(order.getChildType() == Constant.PaotuiTypeEnum.HELP_TAKE.getCode()){
                //帮我送
                if(Integer.parseInt(MasterConstants.MasterOrderCurrentStatus.STATUS_2.getCode())
                        < Integer.parseInt(accitity.getCurrentStatus())){
                    flag = true;
                }
            }
            if(order.getChildType() == Constant.PaotuiTypeEnum.HELP_SEND.getCode()){
                //帮我取
                if(Integer.parseInt(MasterConstants.MasterOrderCurrentStatus.STATUS_2.getCode())
                        <= Integer.parseInt(accitity.getCurrentStatus())){
                    flag = true;
                }
            }
            if(order.getChildType() == Constant.PaotuiTypeEnum.ANY_BUY.getCode()){
                //随意购
                if(Integer.parseInt(MasterConstants.MasterOrderCurrentStatus.STATUS_2.getCode())
                        <= Integer.parseInt(accitity.getCurrentStatus())){
                    flag = true;
                }
            }

        }else if( accitity !=null){
            //技术服务
            if(Integer.parseInt(MasterConstants.MasterOrderCurrentStatus.STATUS_3.getCode())
                    < Integer.parseInt(accitity.getCurrentStatus())){
                flag = true;
            }
        }

        if(master != null && flag){
            //平台设置的取消订单比例
            BigDecimal sysRate = agentServices.getById(order.getAgentId()).getCancelOrder();
            if(sysRate != null && sysRate.compareTo(new BigDecimal(0.00)) != 0){
                //sysRate = new BigDecimal(0.50);//默认50%

                //如果订单流程已是我已到达，则扣款sysRate%，一半给师傅，一半退到用户余额（只有送货中的订单）
                BigDecimal tempAmount = orderAmount.multiply(sysRate.divide(new BigDecimal(100)));
                if(tempAmount !=null) {
                    if(tempAmount.compareTo(orderAmount)>0){
                        tempAmount = orderAmount;
                        orderAmount = new BigDecimal(0.00);
                    }else{
                        orderAmount = orderAmount.subtract(tempAmount);
                        if (orderAmount == null || orderAmount.compareTo(new BigDecimal(0.00)) == 0) {
                            orderAmount = new BigDecimal(0.00);
                        }
                    }

                    BigDecimal tempAmount2 = tempAmount.multiply(new BigDecimal(0.50));
                    //记录分站收益  azy
                    SysAgent agent = agentServices.getById(order.getAgentId());
                    agentAccountDetailService.insertAgentAccountDetail(order.getAgentId(), Constant.AgentAccountTranTypeEnum.PERCENTAGE.getCode().toString(),
                            "用户取消订单扣款" + order.getOrderNo(), tempAmount2, agent.getBalance(), order.getOrderNo());
                    agentServices.updateBalance(order.getAgentId(), Constant.InOutEnum.IN.getCode().toString(), tempAmount2);

                    //完成师傅余额增长
                    BigDecimal balance = Optional.ofNullable(tempAmount2).orElse(BigDecimal.ZERO).add(master.getAccountBalance());
                    master.setAccountBalance(balance);
                    if (userService.updateById(master)) {
                        //保存余额变动明细
                        UserAccountDetail userAccountDetail = new UserAccountDetail();
                        userAccountDetail.setAccountType("1");
                        userAccountDetail.setAccoutWay(1L);
                        userAccountDetail.setAmount(tempAmount2.toString());
                        userAccountDetail.setCreateDt(new Date());
                        userAccountDetail.setDetailType("2");
                        userAccountDetail.setInOutType("1");
                        userAccountDetail.setTranDesc("用户取消订单:" + order.getOrderNo());
                        userAccountDetail.setUserId(order.getMasterId());
                        userAccountDetail.setStatus("0");
                        userAccountDetail.setOutTradeNo(order.getOrderNo());
                        userAccountDetail.setTranAmount(master.getAccountBalance());
                        userAccountDetailService.save(userAccountDetail);
                    } else {
                        logger.error("用户取消订单[%s],师傅余额变动失败", order.getOrderNo());
                    }
                }
            }
        }

        //修改用户余额
        User user = userService.getById(order.getUserId());
        //Optional.ofNullable(order).orElseThrow(() -> new ServerInternalErrorException(ErrorEnum.USER_NOT_EXISTS));
       // BigDecimal balance = Optional.ofNullable(orderAmount).orElse(BigDecimal.ZERO).add(user.getAccountBalance());
       // user.setAccountBalance(balance);
        //if (userService.updateById(user)) {
            /*//保存余额变动明细-退款到余额
            UserAccountDetail userAccountDetail = new UserAccountDetail();
            userAccountDetail.setAccountType("1");
            userAccountDetail.setAccoutWay(1L);
            userAccountDetail.setAmount(orderAmount.toString());
            userAccountDetail.setCreateDt(new Date());
            userAccountDetail.setDetailType("2");
            userAccountDetail.setInOutType("7");
            userAccountDetail.setTranDesc("订单退款:" + order.getOrderNo());
            userAccountDetail.setUserId(order.getUserId());
            userAccountDetail.setStatus("0");
            detailService.save(userAccountDetail);*/
            //修改金额原路退回
            //orderAmount = new BigDecimal("0.01");//测试0.01
            if(order.getPayType() == Constant.PayTypeEnum.WXPAY.getCode()){
                if(!wxpayController.refound(order, orderAmount)){
                    throw new ServerInternalErrorException(ErrorEnum.DO_FAIL);
                }
            }else if (order.getPayType() ==  Constant.PayTypeEnum.WXXCXPAY.getCode()){
                if(!xcxpayController.refound(order, orderAmount)){
                    throw new ServerInternalErrorException(ErrorEnum.DO_FAIL);
                }
            }else if (order.getPayType() ==  Constant.PayTypeEnum.ALIPAY.getCode()){
                if(!alipayController.refound(order, orderAmount)){
                    throw new ServerInternalErrorException(ErrorEnum.DO_FAIL);
                }
            }
            //修改订单状态
            order.setStatus(Constant.OrderStatusEnum.CANCLE.getCode());
            if(isAuto){
                order.setCancleBy(1);//系统
            }else{
                order.setCancleBy(2);//个人取消
            }
            order.setCancleTime(new Date());

            order.setUpdateAt(new Date());
            if(this.updateById(order)){
                    //扩展参数
                    OrderMore om = this.queryOrderById(order.getId());
                //if(Constant.OrderStatusEnum.WAIT_ACCEPT.getCode() != tempStatus){
                    if(order.getMasterId() != null) {
                        userMasterService.refusedScore(order);//拒接订单扣分处理
                        Map<String,Object> map = new HashMap<>();
                        if(om != null){
                            map.put("type", 2);//1-自动派单 2-取消 3-人工派单 4-新订单
                            map.put("orderId", om.getOrderId());
                            map.put("orderNo", om.getOrderNo());
                            map.put("orderType", om.getOrderType());
                            map.put("orderTypeName", om.getOrderTypeName());
                            map.put("amount", om.getAmount());
                            map.put("orderChildType", om.getOrderChildType());
                            map.put("orderChildTypeName", om.getOrderChildTypeName());
                            map.put("fromAddress", om.getFromAddress());
                            map.put("toAddress", om.getToAddress());
                        }
                        try{
                            //缓存推送弹窗订单id
                            User users = userService.getById(order.getMasterId());
                            String ids = users.getPopupQuxiao();
                            if(ids == null){
                                ids = om.getOrderId().toString();
                            }else{
                                ids = ids + ","+om.getOrderId().toString();
                            }
                            users.setPopupQuxiao(ids);
                            userService.updateById(users);
                        }catch (Exception e){
                            e.printStackTrace();
                        }

                        //通知推送师傅
                        sysMessageService.saveMessage("用户取消订单", "用户因:" + order.getCancleRemark()
                                + "取消订单[" + order.getOrderNo() + "]", true, order.getMasterId(), map);

                    }

                    //如果是自动取消通知用户
                    if(isAuto){
                        String message = "订单-"+om.getOrderTypeName()+"-"+om.getOrderChildTypeName()+"已取消";
                        sysMessageService.saveMessage("订单已被取消", message, true, order.getUserId());
                    }
               // }
            }
        //} else {
       //     logger.error("用户取消订单[%s],用户余额变动失败", order.getOrderNo());
       //     return false;
       // }
        return true;
    }


    /**
     * 订单池新订单发送通知
     * 新订单这块推送需要改一下，新订单推送以订单池是否有未接单为准，不再以下新订单推送，每间隔一次查询一下订单池的订单，如果有新订单就推送，没有就不推送，
     * 有新订单，就是您有新的订单语音（新订单和指派订单时不关联的，按调整后的业务是只要查询到订单池有新订单就推送） 指派订单就是平台指派订单了语音，取消订单就是订单取消语音
     * @return
     * 要保证师傅的地理位置是最新的
     */
    public int newOrderPush(){
        //新下单不再推送
		int count = 0;
		//查询所有在接单中的师傅
		List<MasterWaitResp> datas = masterServices.findWaitMaster(null, null,null,null,"1","1","1", "1");
		if(datas == null || datas.size() == 0){
			//TODO 没有师傅接单
		}else {
			for(MasterWaitResp master:datas){
                //查询是否自动派单，如果是不返回数据
                SysAgent agent = agentServices.getById( master.getAgentId());
				//通知推送师傅
				if(master != null && !"auto".equals(agent.getDispatchType())) {
                    NearOrderReq nearOrderReq = new NearOrderReq();
                    nearOrderReq.setDistanceLimit(MasterConstants.KILO_METRE);
                    //nearOrderReq.setAgentId();
                    nearOrderReq.setLatitude(master.getLatitude());
                    nearOrderReq.setLongitude(master.getLongitude());
                    Map<String, String> servcieMap = userMasterService.getMasterServiceType(master.getMasterId());
                    List<OrderNearResp> nearResps = new ArrayList<>();
                    if (master !=null){
                        nearResps = this.findNearOrderList(nearOrderReq, master.getAgentId(), servcieMap,master.getMasterId());
                        if (CollectionUtils.isNotEmpty(nearResps)){
                            count++;
                            OrderNearResp om = nearResps.get(0);
                            Map<String,Object> map = new HashMap<>();
                            if(om != null){
                                map.put("type", 4);//1-自动派单 2-取消 3-人工派单 4-新订单  5-催单
                                map.put("orderId", "");
                                map.put("orderNo", om.getOrderNo());
                                map.put("orderType", om.getType());
                                map.put("orderTypeName", om.getOrderTypeDec());
                                map.put("amount", om.getAmount());
                                map.put("orderChildType", om.getChildType());
                                map.put("orderChildTypeName","");
                                map.put("fromAddress", om.getFromAddress());
                                map.put("toAddress", om.getToAddress());
                            }
                            sysMessageService.saveMessage("阿四服务新订单", "系统有新的订单，请及时处理。", true, master.getMasterId(),map);
                        }
                    }
				}
			}
		}
		return count;
    }

    /**
     * 计算收入
     * @return
     */
    public Map<String,BigDecimal> getIncome(String orderNo){
        Map<String,BigDecimal> map = new HashMap();
        Order order = this.findOrderByOrderNo(orderNo);
        //师傅提成比例
        BigDecimal masterRate , agentRate, sysRate = BigDecimal.ZERO;
        //平台提成比例
        sysRate = agentServices.getById(order.getAgentId()).getProportion();

        if(order.getType()==Constant.OrderTypeEnum.PAO_TUI.getCode()&&order.getHasPartner()!=1){//如果是跑腿的订单，根据物品品类取师傅提成比例
            SysAgentCategoryCfg cfg = cfgService.getById(order.getCategoryId());
            if (cfg !=null){
                masterRate = cfg.getDrawRate();
            }else{
                logger.info("分站提成费率为空:{}", JSON.toJSONString(order));
                masterRate = BigDecimal.ZERO;
            }
        }else if(order.getHasPartner()==1){//技术服务类订单，根据服务类型取师傅提成比例
            User hasUser = userService.getById(order.getUserId());
            masterRate = hasUser.getPartnerScale()!=null?hasUser.getPartnerScale():BigDecimal.ZERO;
        }else{
            AgentServ serv = agentServService.queryServByAgentIdAndCode(order.getAgentId(),order.getType().toString(),order.getChildType().toString());
//            masterRate = new BigDecimal(100).subtract(serv.getAgentRate());
            masterRate = serv.getAgentRate();
        }
        //判断师傅提成比例是否超过上限 ，
        if(masterRate.compareTo(new BigDecimal(100).subtract(sysRate))==1){
            masterRate = new BigDecimal(100).subtract(sysRate);
        }

        BigDecimal orderServerFee = new BigDecimal(0);
        //服务费+深夜服务费+特殊天气服务费+超重费
        if (order.getPriceWay()!=null&&order.getPriceWay()==1){
            orderServerFee = order.getAnyhelpFee();
        }else if (order.getPriceWay()!=null&&order.getPriceWay()==2){
            orderServerFee = order.getOnsiteFee();
        }else {
            orderServerFee = order.getServiceFee()==null?new BigDecimal(0):order.getServiceFee();
        }
        BigDecimal fee =  orderServerFee
                .add(order.getNightFee()==null?BigDecimal.ZERO:order.getNightFee())
                .add(order.getOtherFee()==null?BigDecimal.ZERO:order.getOtherFee())
                .add(order.getOverweightFee()==null?BigDecimal.ZERO:order.getOverweightFee());


        BigDecimal masterIncome = fee.multiply(masterRate).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);
        //BigDecimal sysIncome = fee.multiply(BigDecimal.ONE.subtract(masterRate.divide(new BigDecimal(100)))).multiply(sysRate.divide(new BigDecimal(100))).setScale(2,BigDecimal.ROUND_HALF_DOWN);;
        BigDecimal sysIncome = fee.multiply(sysRate).divide(new BigDecimal(100),2,BigDecimal.ROUND_HALF_UP);
        BigDecimal agentIncome = fee.subtract(masterIncome).subtract(sysIncome);
        //使用了优惠券，全部算作平台成本，
        sysIncome = sysIncome.subtract(order.getCouponAmount()==null?BigDecimal.ZERO:order.getCouponAmount());
        map.put("master",masterIncome);
        map.put("agent",agentIncome);
        map.put("sys",sysIncome);
        return map;
    }

    public static void main(String[] a){


    }


}

